home *** CD-ROM | disk | FTP | other *** search
/ Software Vault: The Gold Collection / Software Vault - The Gold Collection (American Databankers) (1993).ISO / cdr26 / netprog.zip / NETPROG.TAR / ping / main.c < prev    next >
C/C++ Source or Header  |  1989-12-17  |  5KB  |  181 lines

  1. /*
  2.  * Copyright (c) 1987 Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms are permitted
  6.  * provided that the above copyright notice and this paragraph are
  7.  * duplicated in all such forms and that any documentation,
  8.  * advertising materials, and other materials related to such
  9.  * distribution and use acknowledge that the software was developed
  10.  * by the University of California, Berkeley.  The name of the
  11.  * University may not be used to endorse or promote products derived
  12.  * from this software without specific prior written permission.
  13.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  14.  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  15.  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  16.  */
  17.  
  18. #ifndef lint
  19. char copyright[] =
  20. "@(#) Copyright (c) 1987 Regents of the University of California.\n\
  21.  All rights reserved.\n";
  22. #endif /* not lint */
  23.  
  24. #ifndef lint
  25. static char sccsid[] = "@(#)ping.c    4.10 (Berkeley) 10/10/88";
  26. #endif /* not lint */
  27.  
  28. #include    "defs.h"
  29.  
  30. /*
  31.  *            P I N G . C
  32.  *
  33.  * Using the InterNet Control Message Protocol (ICMP) "ECHO" facility,
  34.  * measure round-trip-delays and packet loss across network paths.
  35.  *
  36.  * Author -
  37.  *    Mike Muuss
  38.  *    U. S. Army Ballistic Research Laboratory
  39.  *    December, 1983
  40.  * Modified at Uc Berkeley
  41.  *
  42.  * Status -
  43.  *    Public Domain.  Distribution Unlimited.
  44.  *
  45.  * Bugs -
  46.  *    More statistics could always be gathered.
  47.  *    This program has to run SUID to ROOT to access the ICMP socket.
  48.  */
  49.  
  50. char    usage[] = "Usage:  ping [ -drv ] host [ datasize ] [ npackets ]\n";
  51. char    hnamebuf[MAXHOSTNAMELEN];
  52. char    *pname;
  53.  
  54. main(argc, argv)
  55. int    argc;
  56. char    **argv;
  57. {
  58.     int            sockoptions, on;
  59.     char            *destdotaddr;
  60.     char            *host_err_str();
  61.     struct hostent        *host;
  62.     struct protoent        *proto;
  63.  
  64.     on = 1;
  65.     pname = argv[0];
  66.     argc--;
  67.     argv++;
  68.  
  69.     sockoptions = 0;
  70.     while (argc > 0 && *argv[0] == '-') {
  71.         while (*++argv[0]) switch (*argv[0]) {
  72.             case 'd':
  73.                 sockoptions |= SO_DEBUG;
  74.                 break;
  75.             case 'r':
  76.                 sockoptions |= SO_DONTROUTE;
  77.                 break;
  78.             case 'v':
  79.                 verbose++;
  80.                 break;
  81.         }
  82.         argc--, argv++;
  83.     }
  84.     if (argc < 1)
  85.         err_quit(usage);
  86.  
  87.     /*
  88.      * Assume the host is specified by numbers (Internet dotted-decimal)
  89.      * and call inet_addr() to convert it.  If that doesn't work, then
  90.      * assume its a name and call gethostbyname() to look it up.
  91.      */
  92.  
  93.     bzero((char *) &dest, sizeof(dest));
  94.     dest.sin_family = AF_INET;
  95.  
  96.     if ( (dest.sin_addr.s_addr = inet_addr(argv[0])) != INADDR_NONE) {
  97.         strcpy(hnamebuf, argv[0]);
  98.         hostname = hnamebuf;
  99.         destdotaddr = NULL;
  100.     } else {
  101.         if ( (host = gethostbyname(argv[0])) == NULL) {
  102.             err_quit("host name error: %s %s",
  103.                         argv[0], host_err_str());
  104.         }
  105.         dest.sin_family = host->h_addrtype;
  106.         bcopy(host->h_addr, (caddr_t) &dest.sin_addr, host->h_length);
  107.         hostname = host->h_name;
  108.         destdotaddr = inet_ntoa(dest.sin_addr.s_addr);
  109.                 /* convert to dotted-decimal notation */
  110.     }
  111.  
  112.     /*
  113.      * If the user specifies a size, that is the size of the data area
  114.      * following the ICMP header that is transmitted.  If the data area
  115.      * is large enough for a "struct timeval", then enable timing.
  116.      */
  117.  
  118.     if (argc >= 2)
  119.         datalen = atoi(argv[1]);
  120.     else
  121.         datalen = DEF_DATALEN;
  122.  
  123.     packsize = datalen + SIZE_ICMP_HDR;
  124.     if (packsize > MAXPACKET)
  125.         err_quit("packet size too large");
  126.     if (datalen >= SIZE_TIME_DATA)
  127.         timing = 1;
  128.  
  129.     /*
  130.      * The user can specify the maximum number of packets to receive.
  131.      */
  132.  
  133.     if (argc > 2)
  134.         npackets = atoi(argv[2]);
  135.  
  136.     /*
  137.      * Fetch our Unix process ID.  We use that as the "ident" field
  138.      * in the ICMP header, to identify this process' packets.
  139.      * This allows multiple copies of ping to be running on a host
  140.      * at the same time.  This identifier is needed to separate
  141.      * the received ICMP packets (since all readers of an ICMP
  142.      * socket get all the received packets).
  143.      */
  144.  
  145.     ident = getpid() & 0xffff;
  146.  
  147.     /*
  148.      * Create the socket.
  149.      */
  150.  
  151.     if ( (proto = getprotobyname("icmp")) == NULL)
  152.         err_quit("unknown protocol: icmp");
  153.     if ( (sockfd = socket(AF_INET, SOCK_RAW, proto->p_proto)) < 0)
  154.         err_sys("can't create raw socket");
  155.     if (sockoptions & SO_DEBUG)
  156.         if (setsockopt(sockfd, SOL_SOCKET, SO_DEBUG, &on,
  157.                                 sizeof(on)) < 0)
  158.             err_sys("setsockopt SO_DEBUG error");
  159.     if (sockoptions & SO_DONTROUTE)
  160.         if (setsockopt(sockfd, SOL_SOCKET, SO_DONTROUTE, &on,
  161.                                 sizeof(on)) < 0)
  162.             err_sys("setsockopt SO_DONTROUTE error");
  163.  
  164.     printf("PING %s", hostname);
  165.     if (destdotaddr)
  166.         printf(" (%s)", destdotaddr);
  167.     printf(": %d data bytes\n", datalen);
  168.     tmin = 99999999;
  169.  
  170.     setlinebuf(stdout);        /* one line at a time */
  171.  
  172.     signal(SIGINT, sig_finish);    /* to let user stop program */
  173.     signal(SIGALRM, sig_alarm);    /* invoked every second */
  174.  
  175.     sig_alarm();    /* start the output going */
  176.  
  177.     recv_ping();    /* and start the receive */
  178.  
  179.     /* NOTREACHED */
  180. }
  181.